package com.javaprint.order.printer;

import com.javaprint.order.exception.PrintException;
import com.javaprint.order.settings.OutData;
import com.javaprint.order.settings.PrintSettings;
import com.javaprint.order.util.QrCodeUtil;
import com.javaprint.order.util.XmlBuilder;
import com.javaprint.order.vo.PrintVo;
import me.javy.helper.Helper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import javax.imageio.ImageIO;
import javax.print.*;
import javax.print.attribute.HashPrintRequestAttributeSet;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.print.*;
import java.io.*;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;


/*
 *这是打印运单的类
 * @author LiQiuLin
 * @date 2020/3/15
 */
@Component
public class PrintOrder implements Printable {


    private static final Logger logger = LoggerFactory.getLogger(PrintOrder.class);
    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    private static PrintOrder myPrint;
    private PrintVo printVo;
    private Integer totalPageCount;
    private static PrintSettings printSettings;
    @PostConstruct
    //通过@PostConstruct实现初始化bean之前进行的操作
    public void init() {
        myPrint = this;
    }
    static {
        try {
            //读取Resource目录下的XML文件
            Resource resource = new ClassPathResource("printSettings.xml");
            //利用输入流获取XML文件内容
            BufferedReader br = new BufferedReader(new InputStreamReader(resource.getInputStream(), "UTF-8"));
            StringBuffer buffer = new StringBuffer();
            String line = "";
            while ((line = br.readLine()) != null) {
                buffer.append(line);
            }
            br.close();
            //XML转为JAVA对象
            PrintSettings settings = (PrintSettings) XmlBuilder.xmlStrToObject(PrintSettings.class, buffer.toString());
            printSettings = settings;
        }catch (Exception e){
            logger.error("异常",e);
        }
    }

    public PrintOrder() {
    }

    public PrintOrder(PrintVo printVo) {
        this.printVo = printVo;
       logger.info("运单编号："+printVo.getOrderCode());
    }

    public Integer getTotalPageCount() {
        return totalPageCount;
    }

    public void setTotalPageCount(Integer totalPageCount) {
        this.totalPageCount = totalPageCount;
    }

    /**
     * 打印方法
     * graphics - 用来绘制页面的上下文，即打印的图形
     * pageFormat - 将绘制页面的大小和方向，即设置打印格式，如页面大小一点为计量单位（以1/72 英寸为单位，1英寸为25.4毫米。A4纸大致为595 × 842点）
     * pageIndex - 要绘制的页面从 0 开始的索引 ，即页号
     */
    @Override
    public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
        logger.info("pageIndex为:" + pageIndex);
        //获取数据
        Graphics2D g2 = (Graphics2D) graphics;
        g2.setColor(Color.black);
        if (pageIndex > totalPageCount - 1) {
            return NO_SUCH_PAGE;
        } else {
            logger.info("开始打印第:" + (pageIndex + 1) + "页");
            g2.translate(pageFormat.getImageableX(), pageFormat.getImageableY());// 转换坐标，确定打印边界

            //打印起点坐标
            double x = pageFormat.getImageableX();  //返回与此 PageFormat相关的 Paper对象的可成像区域左上方点的 x坐标。
            double y = pageFormat.getImageableY();  //返回与此 PageFormat相关的 Paper对象的可成像区域左上方点的 y坐标。

            //Font.PLAIN： 普通样式常量  Font.ITALIC 斜体样式常量 Font.BOLD 粗体样式常量。
            List<OutData> data = printSettings.getDataSet().getData();
            OutData outData = data.get(0);
            String fontName = outData.getFontName();
            Integer size = outData.getSize();
            //16号字体
            Font firstFont = new Font(fontName, Font.BOLD, size);
            g2.setFont(firstFont);//设置标题打印字体
            float height = firstFont.getSize2D();//获取字体的高度

            String fasterName = printVo.getFasterName();
            //第一行
            String startAddress = checkNull(printVo.getStartAddress());
            String areaShortCode = checkNull( printVo.getAreaShortCode());
            String startAddressPhone = checkNull(printVo.getStartAddressPhone());
            Integer x0 = outData.getX();
            Integer y0 = outData.getY();
            g2.drawString(startAddress+""+areaShortCode+"  电话："+startAddressPhone+" "+fasterName,(float) x + x0, (float) y +y0);
            //中间很多删掉了，自己可以组装

            //第二行
            //先生成一个二维码图片
            String strQRCode = printVo.getStrQRCode();
            Integer qrcodeSize = printSettings.getQrcodeSize();
            QrCodeUtil util = new QrCodeUtil(100,100,strQRCode);
            String name = "";
            String orderCode = printVo.getOrderCode();
            try {
                byte[] b = util.createQRCode();
                name = printSettings.getBasePath()+orderCode+".png";
                OutputStream os = new FileOutputStream(name);
                os.write(b);
                os.close();
            }catch (Exception e){
                logger.error("异常",e);
            }
            //把图片画到上
            try {
                File file=new File(name);
                if(!file.exists()){
                    file.mkdir();
                }
                BufferedImage image = ImageIO.read(file);
                x0 = data.get(1).getX();
                y0 = data.get(1).getY();
                g2.drawImage(image,x0,y0,qrcodeSize,qrcodeSize,null);
            } catch (IOException e) {
                logger.error("获取二维码图像异常",e);
            }
            return PAGE_EXISTS;
        }
    }

    private String checkNull(Object field){
        if(StringUtils.isEmpty(field)){
            return "";
        }else {
            return String.valueOf(field);
        }
    }



    public void doPrint(Printable printable) {
        try {
            PrintOrder myPrint = new PrintOrder();
            //Book 类提供文档的表示形式，该文档的页面可以使用不同的页面格式和页面 painter
            Book book = new Book(); //要打印的文档
            //PageFormat类描述要打印的页面大小和方向
            PageFormat pf = new PageFormat();  //初始化一个页面打印对象
            pf.setOrientation(PageFormat.PORTRAIT); //设置页面打印方向，从上往下，从左往右
            //设置打印纸页面信息。通过Paper设置页面的空白边距和可打印区域。必须与实际打印纸张大小相符。
            Paper paper = new Paper();
            // 纸张大小A5
            Integer paperHeight = printSettings.getPaper().getPaperHeight();
            Integer paperWidth = printSettings.getPaper().getPaperWidth();

            paper.setSize(paperWidth, paperHeight);
            // A4(595 X 842)设置打印区域 A4纸的默认X,Y边距是72
            Integer x = printSettings.getPaper().getX();
            Integer y = printSettings.getPaper().getY();
            Integer width = printSettings.getPaper().getWidth();
            Integer height = printSettings.getPaper().getHeight();
            paper.setImageableArea(x, y, width, height);
            pf.setPaper(paper);
            book.append(printable, pf, this.totalPageCount);
            PrinterJob job = PrinterJob.getPrinterJob();   //获取打印服务对象
            // 构建打印请求属性集
            HashPrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
            // 设置打印格式，因为未确定类型，所以选择autosense
            DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE;
            // 查找所有的可用的打印服务
            PrintService printServices[] = PrintServiceLookup.lookupPrintServices(flavor, pras);
            PrintService myPrinter = null;
            String choosePrint = printSettings.getPrintName();
            if(Helper.isNotEmpty(printServices)){
                for (PrintService service : printServices) {
                    String name = service.getName();
                    String serviceName = checkNull(name);
                    if(serviceName.contains(choosePrint)){
                        myPrinter = service;
                        logger.info("运单选择打印："+serviceName);
                        break;
                    }
                }
            }
            if(Helper.isEmpty(myPrinter)){
                logger.error(new Date()+",打印运单没有服务:"+choosePrint);
                throw new PrintException("没有打印运单的打印机"+choosePrint);
            }
            //可以输出打印机的各项属性
            job.setPrintService(myPrinter);
            job.setPageable(book);  //设置打印类
            job.print();
        } catch (Exception e) {
            logger.error("打印运单异常",e);
        }
    }

}